package com.jh.fcsm.util.security;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;

public final class MD5Utils {
    private static final String ALGORITHM_MD5 = "MD5";

    private static final String UTF_8 = "UTF-8";
    //szx
    private static final String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
            "e", "f"};

    private MD5Utils() {
    }

    /**
     * md5加密
     *
     * @param str
     * @return
     */
    public static String getMD5Str(String str) {
        MessageDigest messageDigest = null;

        try {
            messageDigest = MessageDigest.getInstance("MD5");

            messageDigest.reset();

            messageDigest.update(str.getBytes(StandardCharsets.UTF_8));
        } catch (NoSuchAlgorithmException e) {
            return "";
        }

        byte[] byteArray = messageDigest.digest();

        StringBuffer md5StrBuff = new StringBuffer();

        for (int i = 0; i < byteArray.length; i++) {
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
                md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
            else
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
        }

        return md5StrBuff.toString();
    }

    public static void main(String[] args) {
        System.out.println(getMD5Str(
                "/ws/geocoder/v1?address=美国&key=PKHBZ-73ECF-PZBJB-NVX5E-LOFB2-R3F5D&oversea=10ZNql2SuShb8nDoaKadOWCDsU4372Dil"));
    }

    //szx
    private static String byteArrayToHexString(byte[] b) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));

        return resultSb.toString();
    }

    /**
     * MD5 32bit 小写.
     *
     * @param readyEncryptStr ready encrypt string
     * @return String encrypt result string
     * @throws NoSuchAlgorithmException
     */
    public static String md5Bit32Lower(String readyEncryptStr) throws Exception {
        if (Objects.nonNull(readyEncryptStr)) {
            MessageDigest md = MessageDigest.getInstance(ALGORITHM_MD5);
            md.update(readyEncryptStr.getBytes(StandardCharsets.UTF_8));
            byte[] b = md.digest();
            StringBuilder su = new StringBuilder();
            for (int offset = 0, bLen = b.length; offset < bLen; offset++) {
                String haxHex = Integer.toHexString(b[offset] & 0xFF);
                if (haxHex.length() < 2) {
                    su.append("0");
                }
                su.append(haxHex);
            }
            return su.toString();
        } else {
            return null;
        }
    }

    //szx
    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    //szx
    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = origin;
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname))
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            else
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
        } catch (Exception exception) {
        }
        return resultString;
    }

    /**
     * sha1加密
     *
     * @param data
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String sha1(String data) {
        // 加盐 更安全一些
        data += "";
        // 信息摘要器 算法名称
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("SHA1");
        } catch (NoSuchAlgorithmException e) {

        }
        if (md == null) {
            throw new RuntimeException("Sha1 加密异常");
        }
        // 把字符串转为字节数组
        byte[] b = data.getBytes();
        // 使用指定的字节来更新我们的摘要
        md.update(b);
        // 获取密文 （完成摘要计算）
        byte[] b2 = md.digest();
        // 获取计算的长度
        int len = b2.length;
        // 16进制字符串
        String str = "0123456789ABCDEF";
        // 把字符串转为字符串数组
        char[] ch = str.toCharArray();

        // 创建一个40位长度的字节数组
        char[] chs = new char[len * 2];
        // 循环20次
        for (int i = 0, k = 0; i < len; i++) {
            byte b3 = b2[i];// 获取摘要计算后的字节数组中的每个字节
            // >>>:无符号右移
            // &:按位与
            // 0xf:0-15的数字
            chs[k++] = ch[b3 >>> 4 & 0xf];
            chs[k++] = ch[b3 & 0xf];
        }

        // 字符数组转为字符串
        return new String(chs);
    }
}
